import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Logger,
  Param,
  Post,
  Query,
} from '@nestjs/common';
import { AppService } from './app.service';
import { decrypt, encrypt as encryptWww } from '@wecom/crypto';
// import { encodingAESKey, token } from './encryptMessage';
import * as crypto from 'crypto';
import { TokenMap } from './token-map';

@Controller()
export class AppController {
  private logger = new Logger('AppController');

  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('/wechat/:id')
  @HttpCode(HttpStatus.OK)
  public getWechatById(
    @Param('id') id: keyof typeof TokenMap,
    @Query()
    query: {
      msg_signature: string;
      timestamp: string;
      nonce: string;
      echostr: string;
    },
  ) {
    const map = TokenMap[id];

    if (map) {
      this.logger.verbose('[query]: ' + JSON.stringify(query));
      this.logger.log(
        '[echostr]: ' +
          JSON.stringify({ echostr: decrypt(map.ak, query.echostr) }),
      );
      return decrypt(map.ak, query.echostr).message;
    }
  }

  @Post('/wechat/:id')
  @HttpCode(HttpStatus.OK)
  public handlerWechatById(
    @Body() body: { encrypt: string },
    @Query() query: object,
    @Param('id') id: keyof typeof TokenMap,
  ) {
    this.logger.verbose('[query]: ' + JSON.stringify(query));
    this.logger.verbose('[body]: ' + JSON.stringify(body));

    const map = TokenMap[id];

    const { encrypt } = body as { encrypt: string };
    const { message } = decrypt(map.ak, encrypt);
    this.logger.verbose('[message]: ' + message);

    const result = encryptWww(
      map.ak,
      JSON.stringify(this.appService.chatMessage(message, map.dtk)),
      '',
      crypto.randomBytes(16),
    );
    const timestamp = String(Date.now());
    const nonceStr = String(Date.now());

    return {
      encrypt: result,
      msgsignature: crypto
        .createHash('sha1')
        .update([map.tk, timestamp, nonceStr, result].sort().join(''))
        .digest('hex'),
      timestamp,
      nonce: nonceStr,
    };
  }

  @Get('/wechat')
  @HttpCode(HttpStatus.OK)
  public getWechat(
    @Query()
    query: {
      msg_signature: string;
      timestamp: string;
      nonce: string;
      echostr: string;
    },
  ) {
    this.logger.verbose('[query]: ' + JSON.stringify(query));
    this.logger.log(
      '[echostr]: ' +
        JSON.stringify({
          echostr: decrypt(
            TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.ak,
            query.echostr,
          ),
        }),
    );
    return decrypt(TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.ak, query.echostr)
      .message;
  }

  @Post('/wechat')
  @HttpCode(HttpStatus.OK)
  public handler(@Body() body: { encrypt: string }, @Query() query: object) {
    this.logger.verbose('[query]: ' + JSON.stringify(query));
    this.logger.verbose('[body]: ' + JSON.stringify(body));
    const { encrypt } = body as { encrypt: string };
    const { message } = decrypt(TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.ak, encrypt);
    this.logger.verbose('[message]: ' + message);

    const result = encryptWww(
      TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.ak,
      JSON.stringify(
        this.appService.chatMessage(
          message,
          TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.dtk,
        ),
      ),
      '',
      crypto.randomBytes(16),
    );
    const timestamp = String(Date.now());
    const nonceStr = String(Date.now());

    return {
      encrypt: result,
      msgsignature: crypto
        .createHash('sha1')
        .update(
          [TokenMap.mWwPOvcMREYtawuEv2WFUUjZA.tk, timestamp, nonceStr, result]
            .sort()
            .join(''),
        )
        .digest('hex'),
      timestamp,
      nonce: nonceStr,
    };
  }
}
